package com.javasm.service.JINXIAOService.impl;

import com.alibaba.fastjson.JSON;
import com.javasm.commons.basic.BaseServiceImpl;
//import com.javasm.commons.config.RedisConfig;
import com.javasm.entity.JINXIAOEntity.SysUser;
import com.javasm.service.JINXIAOService.SysRoleService;
import com.javasm.service.JINXIAOService.SysUserService;
import com.javasm.dao.JINXIAODao.SysUserDao;
import com.javasm.task.async.AsynTaskManager;
import com.javasm.util.EmailUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.ValueOperations;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import javax.mail.MessagingException;
import java.util.List;

@Service
@Slf4j
public class SysUserServiceImpl extends BaseServiceImpl<SysUserDao, SysUser> implements SysUserService {
    @Resource
    private SysUserDao ud;

    @Resource
    private SysRoleService roleService;
//    @Autowired
//    private EmailUtil emailUtil;


    @Autowired
    private RedisTemplate<String, Object> redisTemplate;

    private   String valicode="valicode:";
    @Override
    public SysUser getUserByName(String uname) {
//        SqlSession sqlSession = sessionFactory.openSession();
//        SysUserDao ud = sqlSession.getMapper(SysUserDao.class);
        //得到代理对象的过程:先从factory打开session,有了session才得到dao接口的代理对象;

        //容器中创建的代理过程:
        // 用原生的代理模式代码,创建dao接口代理对象到容器,当我们执行代理对象中的方法时,才打开session.执行session的insert,update,delte,selectOne,selectList
        SysUser u= ud.queryUserByName(uname);
        log.info("查询结果:"+JSON.toJSONString(u));

        //redis的类型操作对象  object  缓存当前登录的用户信息
        ValueOperations<String, Object> ObjectValueOperations = redisTemplate.opsForValue();
        ObjectValueOperations.set("sysUser:"+u.getUphone(), JSON.toJSONString(u));

//        sqlSession.close();
        return u;
    }

    @Override
    public List<SysUser> queryUserAndDeptList(SysUser obj) {
        List<SysUser> sysUsers = this.baseDao.queryUserAndDeptName(obj);
        return sysUsers;
    }

    @Override
    public void sendValicode(String loginPhone) {
        //redis的类型操作对象  object
        ValueOperations<String, Object> ObjectValueOperations = redisTemplate.opsForValue();
        //生成一个验证码
        String code= randomValicode();
        //redis缓存验证码
        ObjectValueOperations.set(valicode+loginPhone,code);
        //发送短信验证码至指定手机号
         log.info("开始发送短信验证码至指定手机号:"+loginPhone);
        //异步线程处理远程调用发送短信验证码，避免出现网络阻塞
//        方式1： 线程 线程池 （手动执行）
        //原始线程,无法控制线程数量的上限
//        Thread thread = new Thread(new Runnable() {
//            @Override
//            public void run() {
//                // 异步执行的代码
//                System.out.println("异步线程任务:"+Thread.currentThread().getName());
//            }
//        });
//        thread.start();

        //线程池处理  线程池的特性： 预创建指定数量的核心线程数100，可以设置队列长度200，可以设置线程拒绝的线程处理方案
        //spring封装线程池 ThreadPoolTaskExecutor
        AsynTaskManager.execute(AsynTaskManager.runnableTask(loginPhone,code));

        //方式2：基于注解方式@Async
//        roleService.sendValicode(loginPhone,code);


        //发送邮件通知
        try {
            EmailUtil.sendJavaMail();
        } catch (MessagingException e) {
            throw new RuntimeException(e);
        }

    }


    @Override
    public boolean checkValicode(String phone, String code) {
        //redis的类型操作对象  object
        ValueOperations<String, Object> ObjectValueOperations = redisTemplate.opsForValue();
        String key  =valicode + phone;
        Object cacheCode = ObjectValueOperations.get(key);//json字符串  JSON.toJSONString(u)
        if(cacheCode==null)return false;

        if(!cacheCode.equals(code)){
            return false;
        }else{
            redisTemplate.delete(key);
            return true;
        }
    }
//   redis的序列化的问题：
//    ObjectInputStream 把序列化流转换成sysUser对象
//    ObjectOutputStream.write()  //要求sysUser必须从Serializable接口派生表示该对象可序列化，write方法把对象转换成序列化流
//    JSON.parseObject((String) s, SysUser.class); //反序列化
//    jSON.toJSONString(u); //序列化
    @Override
    public SysUser getUserByPhone(String phone) {

        //redis的类型操作对象  object
        ValueOperations<String, Object> ObjectValueOperations = redisTemplate.opsForValue();

        String key  ="users:"+phone;
        Object s =  ObjectValueOperations.get(key);//ObjectValueOperations.get 当前get方法，内部使用ObjectInputStream.readObject()  反序列化 把序列化流转换成sysUser对象
        if(s!=null){
            if("".equals(s))return null;
            SysUser sysUser = JSON.parseObject((String) s, SysUser.class); //转目标对象，传入对象
            return sysUser;
        }else{
            //缓存中没有数据
            SysUser u = this.baseDao.queryUserByPhone(phone);
            ObjectValueOperations.set(key,u);// ObjectValueOperations.set 当前set方法，内部使用ObjectOutputStream.write()  序列化 把对象转换成序列化流
            return u;
        }
    }

    public static String randomValicode(){ //随机生成一个字符串
        //100000-999999
        int r = (int)(Math.random()*(999999-100000)+100000);
        return String.valueOf(r);
    }
}